<?php
/**
 * @version		$Id: multisite.php 34 2009-08-17 14:47:55Z naveen.gavini $
 * @package		Joomla
 * @subpackage	Joomla Multisite
 * @copyright	Copyright (C) 2009 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant to the
 * GNU General Public License, and as distributed it includes or is derivative
 * of works licensed under the GNU General Public License or other free or open
 * source software licenses. See COPYRIGHT.php for copyright notices and
 * details.
 */

// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.model');
jimport('joomla.database.database');
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');
jimport('joomla.user.helper');

/**
 * Multisite Multisite Model
 *
 * @package    Multisite
 * @subpackage Components
 */
class MultisitesModelMultisite extends JModel
{
	/**
	 * Constructor that retrieves the ID from the request
	 *
	 * @access	public
	 * @return	void
	 */
	function __construct()
	{
		parent::__construct();

		$array = JRequest::getVar('cid',  0, '', 'array');
		$this->setId((int)$array[0]);
	}

	/**
	 * Method to set the multisite identifier
	 *
	 * @access	public
	 * @param	int Multisite identifier
	 * @return	void
	 */
	function setId($id)
	{
		// Set id and wipe data
		$this->_id		= $id;
		$this->_data	= null;
	}

	/**
	 * Method to get a multisite
	 * @return object with data
	 */
	function &getData()
	{
		// Load the data
		if (empty( $this->_data )) {
			$query = ' SELECT * FROM #__multisite WHERE id = '.$this->_id;
			$this->_db->setQuery($query);
			$this->_data = $this->_db->loadObject();
		}
		if (!$this->_data) {
			$this->_data = new stdClass();
			$this->_data->id = 0;
			$this->_data->name = null;
			$this->_data->url = null;
			$this->_data->prefix = null;
		}
		return $this->_data;
	}

	/**
	 * Method to get tables associated with id
	 * @return array with tables
	 */
	function &getTables()
	{
		$db =& JFactory::getDBO();
		$query = ' SELECT * FROM #__multisite WHERE id = '.$this->_id;
		$this->_db->setQuery($query);
		$this->_data = $this->_db->loadObject();

		if(!empty($this->_data->prefix)){
			$query= 'SHOW TABLES LIKE '.$db->quote($this->_data->prefix."%");
			$db->setQuery($query);
			$list_tables=$db->loadResultArray();
			return $list_tables;
		}
	}
	/**
	 * Method to get all views
	 * @return array with views
	 */
	function &getViews()
	{
		$db =& JFactory::getDBO();
		$query = 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS';
		$db->setQuery($query);
		$list_views=$db->loadResultArray();
		return $list_views;
	}


	/**
	 * Method to store a new record
	 *
	 * @access	public
	 * @return	boolean	True on success
	 */
	function store()
	{
		$row =& $this->getTable();

		$data = JRequest::get( 'post' );
		$db =& JFactory::getDBO();

		// Bind the form fields to the multisite table
		if (!$row->bind($data)) {
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// Validate database table prefix.
		if (!preg_match('#^[a-zA-Z]+[a-zA-Z0-9_]*$#', $data[prefix])) {
			$this->setError(JText::_('MYSQLPREFIXINVALIDCHARS'));
			return false;
		}

		// Validate length of database table prefix.
		if (strlen($data[prefix]) > 15) {
			$this->setError(JText::_('MYSQLPREFIXTOOLONG'));
			return false;
		}

		// Get config directories
		$path=JPATH_BASE;
		$orig=JPATH_CONFIGURATION.DS.'configuration.php';
		$orig_conf=JFile::read($orig);
		$orig_conf=str_replace($db->getPrefix(), $data[prefix], $orig_conf);
			
		$path=str_replace('administrator', 'config', $path);
		$config_list=JFolder::folders($path);

		// Get urls
		$url=$data[url];
		$url=str_replace('http://', '', $url);
		$url=str_replace('https://', '', $url);
		$url=str_replace('/', '',$url);

		// Check if already exists
		$exists=0;
		foreach ($config_list as $config){
			if (strpos($config, $url) !== false) {
				$exists=1;
				return false;
			}
		}
		if ($exists==0){
			JFolder::create($path.'/'.$url,0755);
			JFile::write($path.'/'.$url.'/configuration.php', &$orig_conf);
		}

		// Use default joomla sql file to install schema
		$sql_path=JPATH_COMPONENT_ADMINISTRATOR;
		$sql_path=$sql_path.'/joomla.sql';
		$install_sql=JFile::read($sql_path);
		$install_sql=preg_replace('/#__/', $data[prefix], $install_sql);
		$install_queries=JDatabase::splitSql($install_sql);
		foreach ($install_queries as $iquery){
			if (preg_match('/'.$data[prefix].'components/', $iquery)){
				$new_table=$data[prefix].'components';
				$old_table=$db->getPrefix().'components';
				$iquery='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
			}
			if (preg_match('/'.$data[prefix].'multisite/', $iquery)){
				$new_table=$data[prefix].'multisite';
				$old_table=$db->getPrefix().'multisite';
				$iquery='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
			}
			$db->setQuery($iquery);
			$db->query();
		}

		// Populate array with table structure
		$orig_tables=$db->getTableList();
		$new_tables;
		$match;
		foreach ($orig_tables as $table)
		{
			$match=0;
			$table=preg_replace('/'.$db->getPrefix().'/', $data[prefix], $table);
			foreach ($install_queries as $iquery){
				if(preg_match('/'.$table.'/', $iquery)){
					$match=1;
				}
			}
			if ($match==0){
				$newtab=preg_replace('/'.$data[prefix].'/', $db->getPrefix(), $table);
				if ($newtab!=$table){
					$new=$db->getTableCreate($newtab);
					$new=preg_replace('/'.$db->getPrefix().'/', $data[prefix], $new[$newtab]);
					if (preg_match("/".$data[prefix]."multisite/", $new)){
						$new_tabl=$data[prefix]."multisite";
						$old_tabl=$db->getPrefix()."multisite";
						$new='CREATE VIEW '.$db->nameQuote($new_tabl).'AS SELECT * FROM '.$db->nameQuote($old_tabl);
					}
					$db->setQuery($new);
					$db->query();
				}
			}
		}

		$salt = JUserHelper::genRandomPassword(32);
		$crypt = JUserHelper::getCryptedPassword($data[admin_pass], $salt);
		$cryptpass = $crypt.':'.$salt;

		// create the admin user
		$installdate 	= date('Y-m-d H:i:s');
		$nullDate 		= $db->getNullDate();
		$query	= 'INSERT INTO '.$data[prefix].'users SET'
		. ' id = 42'
		. ', name = '.$db->quote('Administrator')
		. ', username = '.$db->quote($data[admin_user])
		. ', email = '.$db->quote($data[admin_email])
		. ', password = '.$db->quote($cryptpass)
		. ', usertype = '.$db->quote('deprecated')		// Need to weed out where this is used
		. ', block = 0'
		. ', sendEmail = 1'
		. ', registerDate = '.$db->quote($installdate)
		. ', lastvisitDate = '.$db->quote($nullDate)
		. ', activation = '.$db->quote('')
		. ', params = '.$db->quote('');
		$db->setQuery($query);

		if (!$db->query()) {
			$this->setError($db->getErrorMsg());
			return false;
		}

		// Map the super admin to the Super Admin Group
		$query = 'INSERT INTO '.$data[prefix].'user_usergroup_map' .
				' SET user_id = 42, group_id = 8';
		$db->setQuery($query);

		if (!$db->query()) {
			$this->setError($db->getErrorMsg());
			return false;
		}

			
		//Install Sample Data
		if (array_key_exists('sample_data', $data)){
			$sql_path=JPATH_COMPONENT_ADMINISTRATOR;
			$sql_path=$sql_path.'/sample_data.sql';
			$install_sql=JFile::read($sql_path);
			$install_sql=preg_replace('/#__/', $data[prefix], $install_sql);
			$install_queries=JDatabase::splitSql($install_sql);
			foreach ($install_queries as $iquery){
				if (!preg_match('/'.$data[prefix].'components/', $iquery) && !preg_match('/'.$data[prefix].'multisite/', $iquery)){
					$db->setQuery($iquery);
					$db->query();
				}
			}
		}

		// Take care of misc tables to ease component sharing
		$query = 'DROP TABLE IF EXISTS '.$data[prefix].'extensions';
		$db->setQuery($query);
		$db->query();
		$new_table=$data[prefix].'extensions';
		$old_table=$db->getPrefix().'extensions';
		$query='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
		$db->setQuery($query);
		$db->query();

		$query = 'DROP TABLE IF EXISTS '.$data[prefix].'access_actions';
		$db->setQuery($query);
		$db->query();
		$new_table=$data[prefix].'access_actions';
		$old_table=$db->getPrefix().'access_actions';
		$query='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
		$db->setQuery($query);
		$db->query();

		$query = 'DROP TABLE IF EXISTS '.$data[prefix].'access_action_rule_map';
		$db->setQuery($query);
		$db->query();
		$new_table=$data[prefix].'access_action_rule_map';
		$old_table=$db->getPrefix().'access_action_rule_map';
		$query='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
		$db->setQuery($query);
		$db->query();

		$query = 'DROP TABLE IF EXISTS '.$data[prefix].'access_assetgroup_rule_map';
		$db->setQuery($query);
		$db->query();
		$new_table=$data[prefix].'access_assetgroup_rule_map';
		$old_table=$db->getPrefix().'access_assetgroup_rule_map';
		$query='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
		$db->setQuery($query);
		$db->query();

		$query = 'DROP TABLE IF EXISTS '.$data[prefix].'access_rules';
		$db->setQuery($query);
		$db->query();
		$new_table=$data[prefix].'access_rules';
		$old_table=$db->getPrefix().'access_rules';
		$query='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
		$db->setQuery($query);
		$db->query();

		$query = 'DROP TABLE IF EXISTS '.$data[prefix].'access_sections';
		$db->setQuery($query);
		$db->query();
		$new_table=$data[prefix].'access_sections';
		$old_table=$db->getPrefix().'access_sections';
		$query='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
		$db->setQuery($query);
		$db->query();

		$query = 'DROP TABLE IF EXISTS '.$data[prefix].'usergroup_rule_map';
		$db->setQuery($query);
		$db->query();
		$new_table=$data[prefix].'usergroup_rule_map';
		$old_table=$db->getPrefix().'usergroup_rule_map';
		$query='CREATE VIEW '.$db->nameQuote($new_table).'AS SELECT * FROM '.$db->nameQuote($old_table);
		$db->setQuery($query);
		$db->query();

		// Make sure the site record is valid
		if (!$row->check()) {
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// Store the web link table to the database
		if (!$row->store()) {
			$this->setError( $row->getErrorMsg() );
			return false;
		}
		return true;
	}

	/**
	 * Method to store an edited record
	 *
	 * @access	public
	 * @return	boolean	True on success
	 */
	function storeEdit()
	{
		$row =& $this->getTable();
		$data = JRequest::get( 'post' );
		$views =&$this->getViews();

		// Bind the form fields to the hello table
		if (!$row->bind($data)) {
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// Get list of multiste tables for site
		$db =& JFactory::getDBO();
		$main_prefix=$db->getPrefix();
		$query= 'SHOW TABLES LIKE '.$db->quote($data[prefix]."%");
		$db->setQuery($query);
		$table_list=$db->loadResultArray();

		$query='SELECT id, prefix, name FROM #__multisite';
		$db->setQuery($query);
		$sites=$db->loadObjectList();

		$query='SELECT TABLE_NAME, VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS';
		$db->setQuery($query);
		$viewdefs=$db->loadObjectList();

		$query='UPDATE name FROM #__multisite WHERE id='.$data[id];
		$db->setQuery($query);
		$db->query();
			
		foreach ($table_list as $table){
			if ($data[$table]!='seperate'){
				// Shared setup has been selected for table
				$new_prefix;
				$new_id;
				foreach($sites as $site){
					if($site->id==$data[$table]){
						$new_prefix=$site->prefix;
						$new_id=$site->id;
					}
				}
				$exists=0;
				foreach ($viewdefs as $viewdef){
					if ($viewdef->TABLE_NAME==$table){
						$temp_table=preg_replace('/'.$data[prefix].'/', $new_prefix, $table);
						if(preg_match('/'.$temp_table.'/', $viewdef->VIEW_DEFINITION)){
							$exists=1;
						}
					}
				}

				if ($exists==0){
					$isview=0;
					// Check if table is a view
					foreach ($views as $view){
						if ($view==$table){
							$isview=1;
						}
					}
					if ($isview==1){
						$query = 'DROP VIEW '.$db->nameQuote($table);
						$db->setQuery($query);
						$db->query();
					} else {
						$query = 'DROP TABLE IF EXISTS '.$db->nameQuote($table);
						$db->setQuery($query);
						$db->query();
					}

					$new_view=preg_replace('/'.$data[prefix].'/', $new_prefix, $table);
					$query= 'CREATE VIEW '.$db->nameQuote($table).'AS SELECT * FROM '.$db->nameQuote($new_view);
					$db->setQuery($query);
					$db->query();
				}
			} else{
				//Seperate setup has been selected for table
				$exists=0;
				foreach ($views as $view){
					if ($table==$view){
						$exists=1;
					}
				}
				if ($exists==1){
					$query = 'DROP VIEW '.$db->nameQuote($table);
					$db->setQuery($query);
					$db->query();

					$sql_path=JPATH_COMPONENT_ADMINISTRATOR;
					$sql_path=$sql_path.'/joomla.sql';
					$install_sql=JFile::read($sql_path);
					$install_sql=preg_replace('/#__/', $data[prefix], $install_sql);
					$install_queries=JDatabase::splitSql($install_sql);
					foreach ($install_queries as $iquery){
						if (preg_match("/".$table."/", $iquery)){
							$db->setQuery($iquery);
							$db->query();
						}
					}

				}
			}
		}

		// Make sure the site record is valid
		if (!$row->check()) {
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// Store the web link table to the database
		if (!$row->store()) {
			$this->setError( $row->getErrorMsg() );
			return false;
		}
		return true;
	}


	/**
	 * Method to delete record(s)
	 *
	 * @access	public
	 * @return	boolean	True on success
	 */
	function delete()
	{
		$cids = JRequest::getVar( 'cid', array(0), 'post', 'array' );
		$row =& $this->getTable();
		$views =&$this->getViews();

		// Drop prefixed tables from database
		$db =& JFactory::getDBO();
		$query = "SELECT prefix FROM ".$db->nameQuote('#__multisite')." WHERE ".$db->nameQuote('id')." = ".$db->quote($cids[0]).";";
		$db->setQuery($query);
		$prefix = $db->loadResult();
		$query= "SELECT url FROM ".$db->nameQuote('#__multisite')." WHERE ".$db->nameQuote('id')." = ".$db->quote($cids[0]).";";
		$db->setQuery($query);
		$url=$db->loadResult();

		$query= 'SHOW TABLES LIKE '.$db->quote($prefix."%");
		$db->setQuery($query);
		$drop_tables=$db->loadResultArray();
		foreach ($drop_tables as $table){
			$isview=0;
			// Check if table is a view
			foreach ($views as $view){
				if ($view==$table){
					$isview=1;
				}
			}
			if ($isview==1){
				$query = 'DROP VIEW '.$db->nameQuote($table);
				$db->setQuery($query);
				$db->query();
			} else {
				$query = 'DROP TABLE IF EXISTS '.$db->nameQuote($table);
				$db->setQuery($query);
				$db->query();
			}
		}

		//  Remove from multisite table
		if (count( $cids )) {
			foreach($cids as $cid) {
				if (!$row->delete( $cid )) {
					$this->setError( $row->getErrorMsg() );
					return false;
				}
			}
		}

		//Remove config file
		$path=JPATH_BASE;
		$path=str_replace("administrator", "config", $path);
		$url=str_replace("http://", "", $url);
		$url=str_replace("https://", "", $url);
		$url=str_replace("/","",$url);
		JFolder::delete($path.'/'.$url);
		return true;
	}

	/**
	 * Method to sync record(s)
	 *
	 * @access	public
	 * @return	boolean	True on success
	 */
	function syncSave()
	{
		$row =& $this->getTable();
		$data = JRequest::get( 'post' );
		$db =& JFactory::getDBO();
		$views =&$this->getViews();

		$query = ' SELECT * FROM #__multisite WHERE id = '.$data[id];
		$this->_db->setQuery( $query );
		$this->_data = $this->_db->loadObject();
			
		$query= 'SHOW TABLES LIKE '.$db->quote($this->_data->prefix."%");
		$db->setQuery($query);
		$list_tables=$db->loadResultArray();

		$query= 'SELECT prefix FROM #__multisite';
		$db->setQuery($query);
		$prefixs=$db->loadResultArray();
		$i=0;
		$temp_tables;
		$prefixarr;
		foreach ($prefixs as $prefix){
			if ($prefix != $this->_data->prefix){
				$query= 'SHOW TABLES LIKE '.$db->quote($prefix."%");
				$db->setQuery($query);
				$temp_tables[$i]=$db->loadResultArray();
				$prefixarr[$i]=$prefix;
				$i++;
			}
		}

		//Remove prefixes off arrays
		for ($i=0; $i < count ($list_tables); $i++){
			$list_tables[$i]=preg_replace('/^'.$this->_data->prefix.'/', '', $list_tables[$i]);
		}

		for ($i=0; $i < count($temp_tables); $i++){
			for ($x=0; $x < count($temp_tables[$i]); $x++){
				$temp_tables[$i][$x]=preg_replace('/^'.$prefixarr[$i].'/', '', $temp_tables[$i][$x]);
			}
		}

		// Populate other sites with missing tables
		for ($i=0; $i < count($temp_tables); $i++){
			foreach ($list_tables as $list_table){
				if (in_array($list_table, $temp_tables[$i]) == FALSE){
					$query=$db->getTableCreate($this->_data->prefix.$list_table);
					$query=$query[$this->_data->prefix.$list_table];
					$query=preg_replace('/'.$this->_data->prefix.'/', $prefixarr[$i], $query);
					$db->setQuery($query);
					$db->query();
				}
			}
		}
			

		// Remove exta tables on other sites
		for ($i=0; $i < count($temp_tables); $i++){
			for ($x=0; $x < count($temp_tables[$i]); $x++){
				if (in_array($temp_tables[$i][$x], $list_tables) == FALSE){
					$isview=0;
					// Check if table is a view
					foreach ($views as $view){
						if ($view==$prefixarr[$i].$temp_tables[$i][$x]){
							$isview=1;
						}
					}
					if ($isview==1){
						$query = 'DROP VIEW '.$db->nameQuote($prefixarr[$i].$temp_tables[$i][$x]);
						$db->setQuery($query);
						$db->query();
					} else {
						$query = 'DROP TABLE IF EXISTS '.$db->nameQuote($prefixarr[$i].$temp_tables[$i][$x]);
						$db->setQuery($query);
						$db->query();
					}
				}
			}
		}
		return true;
	}
}